home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / formats / iff / newiff.lzh / NewIFF / NewIFF.lzh / newiff / modules / copychunks.c < prev    next >
C/C++ Source or Header  |  1992-05-18  |  5KB  |  198 lines

  1. /* copychunks
  2.  *
  3.  * For Read/Modify/Write programs and other programs that need
  4.  *   to close the IFF file but still reference gathered chunks.
  5.  * Copies your gathered property and collection chunks
  6.  *   from an iff context so that IFF handle may be
  7.  *   closed right after parsing (allowing file or clipboard to
  8.  *   to be reopened for read or write by self or other programs)
  9.  *
  10.  * The created list of chunks can be modified and written
  11.  *   back out to a new handle with writechunklist().
  12.  *
  13.  * If you have used copychunks(), remember to free the copied
  14.  *   chunks with freechunklist(), when ready, to deallocate them.
  15.  * 
  16.  * Note that this implementation is flat and is suitable only
  17.  *   for simple FORMs.
  18.  */
  19.  
  20. #include "iffp/iff.h"
  21.  
  22. /* copychunks()
  23.  *
  24.  * Copies chunks specified in propchks and collectchks
  25.  *   FROM an already-parsed IFFHandle
  26.  *   TO a singly linked list of Chunk structures,
  27.  * and returns a pointer to the start of the list.
  28.  *
  29.  * Generally you would store this pointer in parseInfo.copiedchunks.
  30.  *
  31.  * You must later free the list of copied chunks by calling
  32.  *   FreeChunkList().
  33.  *
  34.  * Reorders collection chunks so they appear in SAME ORDER
  35.  * in chunk list as they did in the file.
  36.  *
  37.  * Returns 0 for failure
  38.  */  
  39. struct Chunk *copychunks(struct IFFHandle *iff,
  40.             LONG *propchks, LONG *collectchks,
  41.             ULONG memtype)
  42.     {
  43.     struct Chunk *chunk, *first=NULL, *prevchunk = NULL;
  44.     struct StoredProperty *sp;
  45.     struct CollectionItem *ci, *cii;
  46.     long error;
  47.     int k, kk, bk;
  48.  
  49.     if(!iff)    return(NULL);
  50.  
  51.     /* Copy gathered property chunks */
  52.     error = 0;
  53.     for(k=0; (!error) && (propchks) && (propchks[k] != TAG_DONE); k+=2)
  54.     {
  55.     if(sp=FindProp(iff,propchks[k],propchks[k+1]))
  56.         {
  57.         D(bug("copying %.4s.%.4s chunk\n",&propchks[k],&propchks[k+1]));
  58.  
  59.         if(chunk=(struct Chunk *)
  60.             AllocMem(sizeof(struct Chunk),memtype|MEMF_CLEAR))
  61.         {
  62.         chunk->ch_Type = propchks[k];
  63.         chunk->ch_ID   = propchks[k+1];
  64.         if(chunk->ch_Data = AllocMem(sp->sp_Size,memtype))
  65.             {
  66.             chunk->ch_Size = sp->sp_Size;
  67.             CopyMem(sp->sp_Data,chunk->ch_Data,sp->sp_Size);
  68.             if(prevchunk)    prevchunk->ch_Next = chunk;
  69.             else         first = chunk;
  70.             prevchunk = chunk;
  71.             }
  72.         else
  73.             {
  74.             FreeMem(chunk,sizeof(struct Chunk));
  75.             chunk=NULL;
  76.             error = 1;
  77.             }
  78.         }
  79.         else error = 1;
  80.         }
  81.     }
  82.  
  83.     /* Copy gathered collection chunks in reverse order */
  84.     for(k=0; (!error) && (collectchks) && (collectchks[k] != TAG_DONE); k+=2)
  85.     {
  86.     if(ci=FindCollection(iff,collectchks[k],collectchks[k+1]))
  87.         {
  88.         D(bug("copying %.4s.%.4s collection\n",&collectchks[k],&collectchks[k+1]));
  89.         for(cii=ci, bk=0; cii; cii=cii->ci_Next)    bk++;
  90.  
  91.         D(bug(" There are %ld of these, first is at $%lx\n",bk,ci));
  92.  
  93.         for( bk; bk; bk--)
  94.         {
  95.          for(kk=1, cii=ci; kk<bk; kk++) cii=cii->ci_Next;
  96.  
  97.         D(bug("  copying number %ld\n",kk));
  98.  
  99.             if(chunk=(struct Chunk *)
  100.             AllocMem(sizeof(struct Chunk),memtype|MEMF_CLEAR))
  101.             {
  102.             chunk->ch_Type = collectchks[k];
  103.             chunk->ch_ID   = collectchks[k+1];
  104.             if(chunk->ch_Data = AllocMem(cii->ci_Size,memtype))
  105.                 {
  106.                 chunk->ch_Size = cii->ci_Size;
  107.                 CopyMem(cii->ci_Data,chunk->ch_Data,cii->ci_Size);
  108.                 if(prevchunk)    prevchunk->ch_Next = chunk;
  109.                 else         first = chunk;
  110.                 prevchunk = chunk;
  111.                 }
  112.             else
  113.                 {
  114.                 FreeMem(chunk,sizeof(struct Chunk));
  115.                 chunk=NULL;
  116.                 error = 1;
  117.                 }
  118.             }
  119.             else error = 1;
  120.         }
  121.         }
  122.     }
  123.  
  124.     if(error)
  125.     {
  126.     if(first) freechunklist(first);
  127.     first = NULL;
  128.     }
  129.  
  130.     return(first);
  131.     }
  132.  
  133.  
  134. /* freechunklist - Free a dynamically allocated Chunk list and
  135.  *   all of its ch_Data.
  136.  *
  137.  * Note - if a chunk's ch_Size is IFFSIZE_UNKNOWN, its ch_Data
  138.  *   will not be deallocated.
  139.  */
  140. void freechunklist(struct Chunk *first)
  141.     {
  142.     struct Chunk *chunk, *next;
  143.  
  144.     chunk = first;
  145.     while(chunk)
  146.     {
  147.     next = chunk->ch_Next;
  148.     if((chunk->ch_Data)&&(chunk->ch_Size != IFFSIZE_UNKNOWN))
  149.         FreeMem(chunk->ch_Data,chunk->ch_Size);
  150.     FreeMem(chunk, sizeof(struct Chunk));    
  151.     chunk = next;
  152.     }
  153.     }
  154.  
  155.  
  156. /* findchunk - find first matching chunk in list of struct Chunks
  157.  *    example  finchunk(pi->copiedchunks,ID_ILBM,ID_CRNG);
  158.  *
  159.  * returns struct Chunk *, or NULL if none found
  160.  */
  161. struct Chunk *findchunk(struct Chunk *first, long type, long id)
  162.     {
  163.     struct Chunk *chunk;
  164.  
  165.     for(chunk=first; chunk; chunk=chunk->ch_Next)
  166.     {
  167.     if((chunk->ch_Type == type)&&(chunk->ch_ID == id)) return(chunk); 
  168.     }
  169.     return(NULL);
  170.     }
  171.  
  172.  
  173. /* writechunklist - write out list of struct Chunk's
  174.  * If data is a null terminated string, you may use
  175.  * IFFSIZE_UNKNOWN as the ch_Szie and strlen(chunk->ch_Data)
  176.  * will be used here as size.
  177.  *
  178.  * Returns 0 for success or an IFFERR
  179.  */
  180. long writechunklist(struct IFFHandle *iff, struct Chunk *first)
  181.     {
  182.     struct Chunk *chunk;
  183.     long size, error = 0;
  184.  
  185.     D(bug("writechunklist: first chunk pointer = $%lx\n",first));
  186.  
  187.     for(chunk=first; chunk && (!error); chunk=chunk->ch_Next)
  188.     {
  189.     size  = (chunk->ch_Size == IFFSIZE_UNKNOWN) ?
  190.             strlen(chunk->ch_Data) :  chunk->ch_Size;
  191.     error = PutCk(iff, chunk->ch_ID, size, chunk->ch_Data);
  192.     D(bug("writechunklist: put %.4s size=%ld, error=%ld\n",
  193.                 &chunk->ch_ID,size, error));
  194.     }
  195.     return(error);
  196.     }
  197.  
  198.